package com.sunday.common.mongo.core;

import com.sunday.common.core.lambda.ColumnMapperOperation;
import com.sunday.common.core.lambda.toolkit.support.ColumnMapper;
import com.sunday.common.core.lambda.toolkit.support.DefaultColumnMapper;
import com.sunday.common.core.lambda.toolkit.support.SFunction;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Field;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * mongo 字段映射
 *
 * @author zsy
 * @since 2024/1/19
 */
public class MongoFieldMapping {

    private static final Map<String, Map<String, ColumnMapper>> COLUMN_CACHE_MAP = new ConcurrentHashMap<>();

    private static final ColumnMapperOperation OPERATION = new ColumnMapperOperation() {
        @Override
        public Map<String, ColumnMapper> getColumnMap(Class<?> target) {
            return COLUMN_CACHE_MAP.get(target.getName());
        }

        @Override
        public Map<String, ColumnMapper> createColumnMap(Class<?> target) {
            Map<String, ColumnMapper> map = new HashMap<>();
            java.lang.reflect.Field[] fields = target.getDeclaredFields();
            for (java.lang.reflect.Field field : fields) {
                //判定字段中包含 org.springframework.data.mongodb.core.mapping.Field 的注解
                if (field.isAnnotationPresent(Field.class)) {
                    String annotationValue = field.getAnnotation(Field.class).value();
                    if (annotationValue.isBlank()) {
                        annotationValue = field.getName();
                    }
                    map.put(field.getName(), DefaultColumnMapper.of(field.getName(), annotationValue));
                }
                //判定字段中包含 org.springframework.data.annotation.Id  的注解
                else if (field.isAnnotationPresent(Id.class)) {
                    map.put(field.getName(), DefaultColumnMapper.of(field.getName(), "_id"));
                }
            }
            COLUMN_CACHE_MAP.put(target.getName(), map);
            return map;
        }
    };

    public static <T> String getColumnName(SFunction<T, ?> func) {
        return OPERATION.getColumnName(func);
    }

}
